package cn.clj1.builtInFunctions;

import cn.clj1.MyClojureInterp;
import cn.clj1.cell.CljCellType;
import cn.clj1.recur.CljRecur;
import cn.clj1.cell.CljCell;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

public class CljLg {

    /**
     * let 语句
     * */
    public static CljCell Clj_list_let(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        if (lst.size() >= 3) {
            CljCell bindings = lst.get(1);
            if (bindings.getCljCellType() == CljCellType.bracket) {
                List<CljCell> pss = (List<CljCell>) bindings.getCell();
                for (int i = 0; i < pss.size(); i += 2) {
                    CljCell c1 = pss.get(i);
                    CljCell c2 = pss.get(i + 1);
                    if (c1.getCljCellType() == CljCellType.symbol || c1.getCljCellType() == CljCellType.percent) {
                        CljCell rs1 = MyClojureInterp.eval(c2, funcHs, cljRecur, new CljCell());
                        funcHs.put(c1.getCell().toString(), rs1);
                    }
                }

                for (int i = 2; i < lst.size(); i++) {
                    if (i == lst.size() - 1) {
                        return MyClojureInterp.eval(lst.get(i), funcHs, cljRecur, new CljCell());
                    }
                    else {
                        MyClojureInterp.eval(lst.get(i), funcHs, cljRecur, new CljCell());
                    }
                }
            }
        } else {
            throw new Exception("unexpected: let 的用法是：(let [bindings*] exprs*) 的！");
        }
        return null;
    }

    /**
     * recur 语句
     * */
    public static CljCell Clj_list_recur(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        if (lst.size() > 1) {
            System.out.println("$$$$$$$$$");
            System.out.println(funcHs.toString());
            System.out.println(cljRecur.getHt().toString());
            System.out.println("****************");
            if (cljRecur.getFuncCellBody() != null) {
                List<CljCell> lstrs = new ArrayList<>();
                for (int i = 1; i < lst.size(); i++) {
                    CljCell cljCell = lst.get(i);
                    CljCell rs1 = MyClojureInterp.eval(cljCell, funcHs, cljRecur, rs);
                    lstrs.add(rs1);
                }
                // 修改传入参数的值
                Hashtable<String, CljCell> ht = CljMyFunc.getParams(cljRecur.getCljFuncParamList(), lstrs);
                return MyClojureInterp.eval(cljRecur.getFuncCellBody(), ht, cljRecur, rs);
            } else {

                Hashtable<String, CljCell> subht = new Hashtable<String, CljCell>();
                for (int i = 1; i < lst.size(); i++) {
                    CljCell rs1 = MyClojureInterp.eval(lst.get(i), funcHs, cljRecur, new CljCell());
                    String key = cljRecur.getHt().get(i);
                    subht.put(key, rs1);
                }

//                int index = 1;
//                Hashtable<String, CljCell> subht = new Hashtable<String, CljCell>();
//                for (int i = 1; i < lst.size(); i++) {
//                    CljCell rs1 = MyClojureInterp.eval(lst.get(i), funcHs, cljRecur, new CljCell());
//                    String key = cljRecur.getHt().get(index);
//                    subht.put(key, rs1);
//                    index++;
//                }
                for (String key : subht.keySet()) {
                    funcHs.replace(key, subht.get(key));
                }

                /**
                 * 2、在调用一次原来的代码
                 * */
                return MyClojureInterp.eval(cljRecur.getCljCell(), funcHs, cljRecur, rs);
            }
        }
        return null;
    }

    /**
     * do 计算
     * */
    public static CljCell Clj_list_do(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        // cond 计算
        if (lst.size() > 1) {
            for (int i = 1; i < lst.size(); i++) {
                if (i == lst.size() - 1) {
                    return MyClojureInterp.eval(lst.get(i), funcHs, cljRecur, rs);
                } else {
                    MyClojureInterp.eval(lst.get(i), funcHs, cljRecur, rs);
                }
            }
        }
        return null;
    }

    /**
     * loop 语句
     * */
    public static CljCell Clj_list_loop(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        if (lst.size() >= 3) {
            CljCell bindings = lst.get(1);
            if (bindings.getCljCellType() == CljCellType.bracket) {
                CljRecur cljRecur1 = new CljRecur(new Hashtable<Integer, String>());
                List<CljCell> pss = (List<CljCell>) bindings.getCell();
                int index = 1;
                for (int i = 0; i < pss.size(); i += 2) {
                    CljCell c1 = pss.get(i);
                    CljCell c2 = pss.get(i + 1);
                    if (c1.getCljCellType() == CljCellType.symbol || c1.getCljCellType() == CljCellType.percent) {
                        CljCell rs1 = MyClojureInterp.eval(c2, funcHs, cljRecur, rs);
                        funcHs.put(c1.getCell().toString(), new CljCell(rs1.getCljCellType(), rs1.getCell()));
                        cljRecur1.getHt().put(index, c1.getCell().toString());
                        index++;
                    }
                }

                for (int i = 2; i < lst.size(); i++) {
                    cljRecur1.setCljCell(lst.get(i));
                    if (i == lst.size() - 1) {
                        return MyClojureInterp.eval(lst.get(i), funcHs, cljRecur1, rs);
                    } else {
                        MyClojureInterp.eval(lst.get(i), funcHs, cljRecur1, rs);
                    }
                }
            }
        } else {
            throw new Exception("unexpected: let 的用法是：(let [bindings*] exprs*) 的！");
        }
        return null;
    }

    /**
     * list 语句
     * */
    public static CljCell my_list(CljCell cell, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        List<CljCell> lst = new ArrayList<>();
        for (CljCell c : (List<CljCell>)cell.getCell()) {
            lst.add(MyClojureInterp.eval(c, funcHs, cljRecur, rs));
        }
        rs.setCell(lst);
        rs.setCljCellType(CljCellType.list);
        return rs;
    }

    /**
     * def 语句
     * */
    public static CljCell Clj_list_def(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        if (lst.size() >= 3) {
            CljCell name = lst.get(1);
            if (name.getCljCellType() == CljCellType.symbol || name.getCljCellType() == CljCellType.percent) {
                CljCell vs = MyClojureInterp.eval(lst.get(lst.size() - 1), funcHs, cljRecur, new CljCell());
                switch (vs.getCljCellType()) {
                    case defn:
                        break;
                    default:
                        funcHs.put(name.getCell().toString(), vs);
                        break;
                }
            }
        }
        return rs;
    }
}
































